﻿using BulletSharp;
using BulletSharp.Math;

namespace Painter3D.PhysicalSys
{
    /// <summary>
    /// 必须已经拥有一个collision组件才能添加，将该物体托付于物理系统更新
    /// </summary>
    partial class RigidBody : Component
    {
        public enum RigidBodyTypeEnum
        {
            /// <summary>
            /// 静态类型，该类型只能用于位置不会发生移动的情形
            /// </summary>
            Static,
            /// <summary>
            /// 动力学类型，该类型会自动更新物体的位置
            /// </summary>
            Dynamic,
            /// <summary>
            /// 运动学类型，该类型受用户的控制，不受物理模拟影响
            /// </summary>
            Kinematic,
        }
        public RigidBodyTypeEnum rigidType
        {
            get; private set;
        }

        private BulletSharp.RigidBody rigidBody;

        public RigidBody(Transform transform, CollisionShape shape, RigidBodyTypeEnum type) : base(transform)
        {
            rigidType = type;
            switch (type)
            {
                case RigidBodyTypeEnum.Static:
                    StaticBody(transform, shape);
                    break;
                case RigidBodyTypeEnum.Dynamic:
                    DynamicBody(transform, shape);
                    break;
                case RigidBodyTypeEnum.Kinematic:
                    KenimaticBody(transform, shape);
                    break;
                default:
                    break;
            }
        }

        public void StaticBody(Transform transform, CollisionShape shape)
        {
            using (var info = new RigidBodyConstructionInfo(0, new MotionStateUpdate(transform), shape))
            {
                rigidBody = new BulletSharp.RigidBody(info);
            }
            if (BulletEngine.world != null)
            {
                BulletEngine.world.AddRigidBody(rigidBody);
            }
        }

        public void DynamicBody(Transform transform, CollisionShape shape)
        {
            Vector3 localInertia = shape.CalculateLocalInertia(1);
            using (var info = new RigidBodyConstructionInfo(1, new MotionStateUpdate(transform), shape, localInertia))
            {
                rigidBody = new BulletSharp.RigidBody(info);
            }
            if (BulletEngine.world != null)
            {
                BulletEngine.world.AddRigidBody(rigidBody);
            }
        }

        public void KenimaticBody(Transform transform, CollisionShape shape)
        {
            using (var info = new RigidBodyConstructionInfo(0, new MotionStateUpdate(transform), shape))
            {
                rigidBody = new BulletSharp.RigidBody(info);
            }
            rigidBody.CollisionFlags |= CollisionFlags.KinematicObject;
            rigidBody.ActivationState = ActivationState.DisableDeactivation;
            if (BulletEngine.world != null)
            {
                BulletEngine.world.AddRigidBody(rigidBody);
            }
        }

        /// <summary>
        /// 向质心施加作用力
        /// </summary>
        /// <param name="force">力的向量</param>
        public void ApplyCentralForce(OpenTK.Vector3 force)
        {
            rigidBody.ApplyCentralForce(force.Convert2BT());
        }

        /// <summary>
        /// 施加转矩
        /// </summary>
        /// <param name="torque">转矩</param>
        public void ApplyTorque(OpenTK.Vector3 torque)
        {
            rigidBody.ApplyTorque(torque.Convert2BT());
        }

        #region 关节函数
        public Point2PointConstraint AddSphereJoint()
        {
            Point2PointConstraint point2PointConstraint = new Point2PointConstraint(rigidBody, new Vector3(0));
            return point2PointConstraint;
        }
        #endregion

        public override void Dispose()
        {
            rigidBody.MotionState.Dispose();
            rigidBody.CollisionShape.Dispose();
            BulletEngine.world.RemoveRigidBody(rigidBody);
            rigidBody.Dispose();
            base.Dispose();
        }
    }
}
